﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace myMapObj
{
    public class moMultiPolyline : moGeometry
    {

        #region 字段

        private moParts _Parts;
        double _MinX = double.MaxValue, _MaxX = double.MinValue;
        double _MinY = double.MaxValue, _MaxY = double.MinValue;

        #endregion

        #region Shapefile读取相关字段
        int byteCount = 0;
        #endregion

        #region 构造函数

        public moMultiPolyline()
        {
            _Parts = new moParts();
        }

        public moMultiPolyline(moPoints points)
        {
            _Parts = new moParts();
            _Parts.Add(points);
        }

        public moMultiPolyline(moParts parts)
        {
            _Parts = parts;
        }

        /// <summary>
        /// 基于文本流(SEGV文件)的构造函数
        /// </summary>
        /// <param name="sr">文本流(SEGV文件)</param>
        public moMultiPolyline(StreamReader sr)
        {
            _Parts = new moParts();
            string strLine;
            string[] data;
            strLine = sr.ReadLine();
            data = strLine.Split(' ');
            //fid = Int32.Parse(data[0]);
            int polylineCount = Int32.Parse(data[0]);
            //int[] firstIndex = new int[polylineCount];
            // int count = 0;
            //循环读取子线段
            for (int i = 0; i < polylineCount; i++)
            {
                moPoints sPoints = new moPoints();
                //firstIndex[i] = count;
                strLine = sr.ReadLine();
                data = strLine.Split(' ');
                int n = Int32.Parse(data[0]);  //子线段中点的个数
                //count += n;
                //循环读取子线段上的点
                for (int j = 0; j < n; j++)
                {

                    double x = Double.Parse(data[2 * j + 1]);
                    double y = Double.Parse(data[2 * j + 2]);
                    sPoints.Add(new moPoint(x, y));
                    if (x < _MinX)
                        _MinX = x;
                    if (x > _MaxX)
                        _MaxX = x;
                    if (y < _MinY)
                        _MinY = y;
                    if (y > _MaxY)
                        _MaxY = y;
                }
                _Parts.Add(sPoints);
            }
        }

        /// <summary>
        /// 基于二进制流(Shapefile)的构造函数
        /// </summary>
        /// <param name="br">二进制流(Shapefile)</param>
        public moMultiPolyline(BinaryReader br)
        {
            _Parts = new moParts();
            int recordNumber;
            int contentLength;  //坐标记录长度
            int shapeType;  //几何类型
            //读取记录头
            recordNumber = Shapefile.ReverseByte(br.ReadInt32());
            contentLength = Shapefile.ReverseByte(br.ReadInt32());
            byteCount += 8;
            //读取记录内容
            shapeType = br.ReadInt32();
            _MinX = br.ReadDouble();
            _MinY = br.ReadDouble();
            _MaxX = br.ReadDouble();
            _MaxY = br.ReadDouble();
            int polylineCount = br.ReadInt32();//子折线个数
            int numPoints = br.ReadInt32();//总的点个数
            byteCount += 44;
            int[] firstIndex = new int[polylineCount];//每个子折线的第一个点下标
            for (int i = 0; i < polylineCount; i++)
                firstIndex[i] = br.ReadInt32();
            byteCount += 4 * polylineCount;
            double x, y;
            for (int i = 0; i < polylineCount; i++)
            {
                moPoints sPoints = new moPoints();
                int count = 0;//当前多边形点的个数
                if (i < polylineCount - 1)
                    count = firstIndex[i + 1] - firstIndex[i];
                else
                    count = numPoints - firstIndex[i];
                for (int j = 0; j < count; j++)
                {
                    x = br.ReadDouble();
                    y = br.ReadDouble();
                    moPoint p = new moPoint(x, y);
                    MercatoProjection projection = new MercatoProjection();
                    p = projection.LngLat2XY(p);
                    sPoints.Add(p);
                }
                _Parts.Add(sPoints);
            }
            byteCount += 16 * numPoints;
            UpdateExtent();
        }

        #endregion

        #region 属性

        /// <summary>
        /// 获取或设置部分集合
        /// </summary>
        public moParts Parts
        {
            get { return _Parts; }
            set { _Parts = value; }
        }

        /// <summary>
        /// 获取最小X坐标
        /// </summary>
        public double MinX
        {
            get { return _MinX; }
        }

        /// <summary>
        /// 获取最大X坐标
        /// </summary>
        public double MaxX
        {
            get { return _MaxX; }
        }

        /// <summary>
        /// 获取最小Y坐标
        /// </summary>
        public double MinY
        {
            get { return _MinY; }
        }

        /// <summary>
        /// 获取最大Y坐标
        /// </summary>
        public double MaxY
        {
            get { return _MaxY; }
        }

        public int ByteCount
        {
            get { return this.byteCount; }
        }

        #endregion

        #region 方法

        public void WriteSEgv(StreamWriter sw)
        {
            Int32 sPartCount = _Parts.Count;
            sw.WriteLine(sPartCount.ToString());
            //循环写入子折线信息
            for (int i = 0; i < sPartCount; i++)
            {
                moPoints sPoints = _Parts.GetItem(i);
                Int32 sPointCount = sPoints.Count;
                string strLine = "";
                strLine += sPointCount.ToString();
                for (int j = 0; j < sPointCount; j++)
                {
                    moPoint sPoint = sPoints.GetItem(j);
                    strLine += " " + sPoint.X.ToString() + " " + sPoint.Y.ToString();
                }
                sw.WriteLine(strLine);
            }
        }

        /// <summary>
        /// 获取外包矩形
        /// </summary>
        /// <returns></returns>
        public moRectangle GetEnvelope()
        {
            moRectangle sRectangle = new moRectangle(_MinX, _MaxX, _MinY, _MaxY);
            return sRectangle;
        }

        /// <summary>
        /// 重新计算坐标范围
        /// </summary>
        public void UpdateExtent()
        {
            CalExtent();
        }

        /// <summary>
        /// 复制
        /// </summary>
        /// <returns></returns>
        public moMultiPolyline Clone()
        {
            moMultiPolyline sMultiPolyline = new moMultiPolyline();
            sMultiPolyline.Parts = _Parts.Clone();
            sMultiPolyline._MinX = _MinX;
            sMultiPolyline._MaxX = _MaxX;
            sMultiPolyline._MinY = _MinY;
            sMultiPolyline._MaxY = _MaxY;
            return sMultiPolyline;
        }

        #endregion

        #region 私有函数

        //计算坐标范围
        private void CalExtent()
        {
            double sMinX = double.MaxValue, sMaxX = double.MinValue;
            double sMinY = double.MaxValue, sMaxY = double.MinValue;
            Int32 sPartCount = _Parts.Count;
            for (Int32 i = 0; i <= sPartCount - 1; i++)
            {
                _Parts.GetItem(i).UpdateExtent();
                if (_Parts.GetItem(i).MinX < sMinX)
                    sMinX = _Parts.GetItem(i).MinX;
                if (_Parts.GetItem(i).MaxX > sMaxX)
                    sMaxX = _Parts.GetItem(i).MaxX;
                if (_Parts.GetItem(i).MinY < sMinY)
                    sMinY = _Parts.GetItem(i).MinY;
                if (_Parts.GetItem(i).MaxY > sMaxY)
                    sMaxY = _Parts.GetItem(i).MaxY;
            }
            _MinX = sMinX;
            _MaxX = sMaxX;
            _MinY = sMinY;
            _MaxY = sMaxY;
        }

        #endregion
    }
}
